import 'dart:convert';

import 'package:redux/redux.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'shopping_item.dart';
import 'shopping_list_action.dart';
import 'shopping_list_reducer.dart';
import 'shopping_list_state.dart';

const SHOPPLINT_LIST_KEY = 'shoppingList';
List<Middleware<ShoppingListState>> shopplingListMiddleware() => [
      TypedMiddleware<ShoppingListState, ReadOfflineAction>(
          _readOfflineActionMiddleware),
      TypedMiddleware<ShoppingListState, AddItemAction>(
          _addItemActionMiddleware),
      TypedMiddleware<ShoppingListState, ToggleItemStateAction>(
          _toggleItemActionMiddleware),
      TypedMiddleware<ShoppingListState, AddItemCountAction>(
          _addItemCountActionMiddleware),
      TypedMiddleware<ShoppingListState, SubItemCountAction>(
          _subItemCountActionMiddleware),
    ];

void _readOfflineActionMiddleware(Store<ShoppingListState> store,
    ReadOfflineAction action, NextDispatcher next) {
  SharedPreferences.getInstance().then((prefs) {
    dynamic offlineList = prefs.get(SHOPPLINT_LIST_KEY);
    if (offlineList != null && offlineList is String) {
      store.dispatch(
          ReadOfflineSuccessAction(offlineList: json.decode(offlineList)));
    }
  });
  next(action);
}

void _addItemActionMiddleware(
    Store<ShoppingListState> store, AddItemAction action, NextDispatcher next) {
  List<Map<String, String>> listToSave =
      _prepareForSave(store.state.shoppingItems, action);
  SharedPreferences.getInstance().then(
      (prefs) => prefs.setString(SHOPPLINT_LIST_KEY, json.encode(listToSave)));
  next(action);
}

void _toggleItemActionMiddleware(Store<ShoppingListState> store,
    ToggleItemStateAction action, NextDispatcher next) {
  List<Map<String, String>> listToSave =
      _prepareForSave(store.state.shoppingItems, action);
  SharedPreferences.getInstance().then(
      (prefs) => prefs.setString(SHOPPLINT_LIST_KEY, json.encode(listToSave)));
  next(action);
}

void _addItemCountActionMiddleware(Store<ShoppingListState> store,
    AddItemCountAction action, NextDispatcher next) {
  List<Map<String, String>> listToSave =
      _prepareForSave(store.state.shoppingItems, action);
  SharedPreferences.getInstance().then(
      (prefs) => prefs.setString(SHOPPLINT_LIST_KEY, json.encode(listToSave)));
  next(action);
}

void _subItemCountActionMiddleware(Store<ShoppingListState> store,
    SubItemCountAction action, NextDispatcher next) {
  List<Map<String, String>> listToSave =
      _prepareForSave(store.state.shoppingItems, action);
  SharedPreferences.getInstance().then(
      (prefs) => prefs.setString(SHOPPLINT_LIST_KEY, json.encode(listToSave)));
  next(action);
}

List<Map<String, String>> _prepareForSave(
    List<ShoppingItem> oldItems, dynamic action) {
  List<ShoppingItem> newItems = [];
  if (action is AddItemAction) {
    newItems = addItemActionHandler(oldItems, action.item);
  }
  if (action is ToggleItemStateAction) {
    newItems = toggleItemStateActionHandler(oldItems, action.item);
  }
  if (action is AddItemCountAction) {
    newItems = addItemCountActionHandler(oldItems, action.item);
  }
  if (action is SubItemCountAction) {
    newItems = subItemCountActionHandler(oldItems, action.item);
  }

  return newItems.map((item) => item.toJson()).toList();
}
